# SPDX-License-Identifier: GPL-2.0+
# config info
# ---------------------------------------------------------------------------
CONFIG_TOOLS_DEBUG=y

# version info
# ---------------------------------------------------------------------------
VERSION          = 2025
PATCHLEVEL       = 02
SUBLEVEL         =
EXTRAVERSION     =
NAME             =

# Do not print "Entering directory ...",
# but we want to display it when entering to the output directory
# so that IDEs/editors are able to understand relative filenames.
MAKEFLAGS += --no-print-directory

# make src dir info
# ---------------------------------------------------------------------------
srctree := .
objtree := .
src		:= $(srctree)
obj		:= $(objtree)

VPATH   := $(srctree)


libs-y += cmd/
libs-y := $(sort $(libs-y))

u-boot-dirs	    := $(patsubst %/,%,$(filter %/, $(libs-y))) tools
u-boot-alldirs	:= $(sort $(u-boot-dirs) $(patsubst %/,%,$(filter %/, $(libs-))))

export srctree objtree VPATH

# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed.
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
#	$(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commands

ifeq ("$(origin V)", "command line")
  KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif

# If the user is running make -s (silent mode), suppress echoing of
# commands

ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4, make执行时会自动赋值
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
  quiet=silent_
endif
else					# make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
  quiet=silent_
endif
endif

export quiet Q KBUILD_VERBOSE

# HOST info
# ---------------------------------------------------------------------------
HOSTARCH      := $(shell uname -m | \
					sed -e s/i.86/x86/ \
	    				-e s/sun4u/sparc64/ \
	    				-e s/arm.*/arm/ \
	    				-e s/sa110/arm/ \
	    				-e s/ppc64/powerpc/ \
	    				-e s/ppc/powerpc/ \
	    				-e s/macppc/powerpc/\
	    				-e s/sh.*/sh/)

HOSTOS       := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
	    			sed -e 's/\(cygwin\).*/cygwin/')

# SHELL used by kbuild
CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
	  					else if [ -x /bin/bash ]; then echo /bin/bash; \
	  					else echo sh; fi ; fi)

HOSTCC       = cc
HOSTCXX      = c++

HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \
				$(if $(CONFIG_TOOLS_DEBUG),-g)
HOSTCXXFLAGS = -O2

# With the move to GCC 6, we have implicitly upgraded our language
# standard to GNU11 (see https://gcc.gnu.org/gcc-5/porting_to.html).
# Some Linux distributions (including RHEL7, SLES13, Debian 8) still
# have older compilers as their default, so we make it explicit for
# these that our host tools are GNU11 (i.e. C11 w/ GNU extensions).
CSTD_FLAG := -std=gnu11
ifeq ($(HOSTOS),linux)
HOSTCFLAGS += $(CSTD_FLAG)
endif

export HOSTARCH HOSTOS 
export CONFIG_SHELL
export HOSTCC HOSTCXX

# board info
# ---------------------------------------------------------------------------
ARCH    ?=

# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif

export ARCH
# generic definitions
# ---------------------------------------------------------------------------
# We need some generic definitions (do not try to remake the file).
scripts/Kbuild.include: ;
include scripts/Kbuild.include

# compile tool info
# ---------------------------------------------------------------------------
# Make variables (CC, etc...)
AS		= $(CROSS_COMPILE)as
# Always use GNU ld
ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
LD		= $(CROSS_COMPILE)ld.bfd
else
LD		= $(CROSS_COMPILE)ld
endif
CC		= $(CROSS_COMPILE)gcc
CPP		= $(CC) -E
AR		= $(CROSS_COMPILE)ar
NM		= $(CROSS_COMPILE)nm
LDR		= $(CROSS_COMPILE)ldr
STRIP   = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
LEX		= flex
YACC    = bison
AWK		= awk
PERL    = perl
PYTHON ?= python
PYTHON2 = python2
PYTHON3 = python3
DTC    ?= $(objtree)/scripts/dtc/dtc
CHECK   = sparse

CHECKFLAGS      := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
		  			-Wbitwise -Wno-return-void -D__CHECK_ENDIAN__ $(CF)

KBUILD_CPPFLAGS := -D__KERNEL__ -D__UBOOT__

KBUILD_CFLAGS   := -Wall -Wstrict-prototypes \
					-Wno-format-security \
					-fno-builtin -ffreestanding $(CSTD_FLAG)
KBUILD_CFLAGS	+= -fshort-wchar -fno-strict-aliasing
KBUILD_AFLAGS   := -D__ASSEMBLY__

# Don't generate position independent code
KBUILD_CFLAGS	+= $(call cc-option,-fno-PIE)
KBUILD_AFLAGS	+= $(call cc-option,-fno-PIE)

export AS LD CC CPP AR NM LDR STRIP OBJCOPY OBJDUMP
export MAKE LEX YACC AWK PERL PYTHON PYTHON2 PYTHON3 DTC CHECK
export HOSTCFLAGS
export CHECKFLAGS KBUILD_CPPFLAGS KBUILD_CFLAGS KBUILD_AFLAGS

# Files to ignore in find ... statements
# ---------------------------------------------------------------------------
export RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o    \
							 -name CVS -o -name .pc -o -name .hg -o -name .git \) \
			  				 -prune -o
export RCS_TAR_IGNORE  := --exclude SCCS --exclude BitKeeper --exclude .svn \
			 			  --exclude CVS --exclude .pc --exclude .hg --exclude .git

# That's our default target when none is given on the command line
PHONY := _all
_all:

# cmd define
# ---------------------------------------------------------------------------

# copy 命令的定义，一般会定义两个，带 quiet_ 前缀的和不带这个前缀的
# 为什么定义两个? 例如 通过 if_changed 函数来调用
# make V=1 ... 会打印 cmd_copy 的内容并且执行 cp $< $@ 命令
# make V=0 ... 会打印 quiet_cmd_copy 的内容并且执行 cp $< $@ 命令
quiet_cmd_copy = COPY    $@
      cmd_copy = cp $< $@

quiet_cmd_mkdir = MKDIR    $@
      cmd_mkdir = mkdir -p $@

quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
      cmd_rmdirs = rm -rf $(rm-dirs)

quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
      cmd_rmfiles = rm -f $(rm-files)

# ===========================================================================
# Rules shared between *config targets and build targets

# Basic helpers built in scripts/
PHONY += scripts_basic
scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

# To avoid any implicit rule to kick in, define an empty command.
scripts/basic/%: scripts_basic ;

%config: scripts_basic FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@
	@python config_head_create.py .config config.h 0
	@rm -f .config.old .config.cmd

# debug target
# ---------------------------------------------------------------------------
print:
	@echo "MAKE_VERSION=$(MAKE_VERSION)"

TEST_TARGET      = test_cmd
TEST_CMD         = test_cmd_copy test_cmd_mkdir
$(TEST_TARGET): $(TEST_CMD)
	@:

CLEAN_FILES += test_cmd_copy
test_cmd_copy: 1.sh
	$(call if_changed,copy)

CLEAN_DIRS += test_cmd_mkdir
test_cmd_mkdir:
	$(call if_changed,mkdir)

# clean
# ---------------------------------------------------------------------------
# Directories & files removed with 'make clean'
CLEAN_DIRS     += 
CLEAN_FILES    += 
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS  += 
MRPROPER_FILES += .config .config.old include/autoconf.mk* include/config.h

# clean - Delete most, but leave enough to build external modules
#
clean: rm-dirs  := $(CLEAN_DIRS)
clean: rm-files := $(CLEAN_FILES)

clean-dirs	    := $(foreach f,$(u-boot-alldirs),$(if $(wildcard $(srctree)/$f/Makefile),$f))
clean-dirs      := $(addprefix _clean_, $(clean-dirs))

PHONY += $(clean-dirs) clean
$(clean-dirs):
	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)

clean: $(clean-dirs)
	$(call cmd,rmdirs)
	$(call cmd,rmfiles)
	@find $(RCS_FIND_IGNORE) \
		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
		-o -name '*.ko.*' -o -name '*.su' \
		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
		-o -name '*.lex.c' -o -name '*.tab.[ch]' \
		-o -name '*.symtypes' -o -name 'modules.order' \
		-o -name modules.builtin -o -name '.tmp_*.o.*' \
		-o -name 'dsdt.aml' -o -name 'dsdt.asl.tmp' -o -name 'dsdt.c' \
		-o -name '*.efi' -o -name '*.gcno' -o -name '*.so' \) \
		-type f -print | xargs rm -f

# mrproper - Delete all generated files, including .config
#
mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
mrproper-dirs      := $(addprefix _mrproper_,scripts)

PHONY += $(mrproper-dirs) mrproper
$(mrproper-dirs):
	$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)

mrproper: clean $(mrproper-dirs)
	$(call cmd,rmdirs)
	$(call cmd,rmfiles)

# distclean
#
PHONY += distclean

distclean: mrproper
	@find $(srctree) $(RCS_FIND_IGNORE) \
		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
		-o -name '.*.rej' -o -name '*%' -o -name 'core' \
		-o -name '*.pyc' \) \
		-type f -print | xargs rm -f

# PHONY 伪目标
# ---------------------------------------------------------------------------	
PHONY += FORCE
FORCE:

# Declare the contents of the .PHONY variable as phony.  We keep that
# information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY)
